home *** CD-ROM | disk | FTP | other *** search
- /* Cursor motion subroutines for XEmacs.
- Copyright (C) 1994 Free Software Foundation, Inc.
- loosely based primarily on public domain code written by Chris Torek
-
- This file is part of XEmacs.
-
- XEmacs is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- XEmacs is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with XEmacs; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Synched up with: FSF 19.28. Substantially different from FSF. */
-
- #include <config.h>
- #include "lisp.h"
-
- #include "device.h"
- #include "device-tty.h"
- #include "frame.h"
- #include "redisplay.h"
-
- #define EXPENSIVE 2000
-
- extern char *tgoto (CONST char *cm, int hpos, int vpos);
- extern void tputs (CONST char *, int, void (*)(int));
-
- static int cm_cost_counter; /* sums up costs */
-
- void evalcost (int c);
- void
- evalcost (int c)
- {
- cm_cost_counter++;
- }
-
- /* Ugh -- cmputc() can't take a device argument, so we pass it in a global */
- struct device *cmputc_device;
-
- void
- cmputc (int c)
- {
- if (termscript)
- fputc (c, termscript);
-
- fputc (c, DEVICE_TTY_DATA (cmputc_device)->outfd);
- }
-
- /*
- * (Re)Initialize the cost factors, given the output speed of the
- * terminal in DEVICE_TTY_DATA (d)->ospeed. (Note: this holds B300,
- * B9600, etc -- ie stuff out of <sgtty.h>.)
- */
- void
- cm_cost_init (struct device *d)
- {
- char *tmp;
-
- cm_cost_counter = 0;
- #define COST(x,e) (x \
- ? (cm_cost_counter = 0, tputs (x, 1, e), cm_cost_counter) \
- : EXPENSIVE)
- #define MINCOST(x,e) ((x == 0) \
- ? EXPENSIVE \
- : (tmp = tgoto(x, 0, 0), COST(tmp,e)))
-
- TTY_COST (d).cm_up = COST (TTY_CM (d).up, evalcost);
- TTY_COST (d).cm_down = COST (TTY_CM (d).down, evalcost);
- TTY_COST (d).cm_left = COST (TTY_CM (d).left, evalcost);
- TTY_COST (d).cm_right = COST (TTY_CM (d).right, evalcost);
- TTY_COST (d).cm_home = COST (TTY_CM (d).home, evalcost);
- TTY_COST (d).cm_low_left = COST (TTY_CM (d).low_left, evalcost);
- TTY_COST (d).cm_car_return = COST (TTY_CM (d).car_return, evalcost);
-
- /*
- * These last three are actually minimum costs. When (if) they are
- * candidates for the least-cost motion, the real cost is computed.
- * (Note that "0" is the assumed to generate the minimum cost.
- * While this is not necessarily true, I have yet to see a terminal
- * for which is not; all the terminals that have variable-cost
- * cursor motion seem to take straight numeric values. --ACT)
- */
-
- TTY_COST (d).cm_abs = MINCOST (TTY_CM (d).abs, evalcost);
- TTY_COST (d).cm_hor_abs = MINCOST (TTY_CM (d).hor_abs, evalcost);
- TTY_COST (d).cm_ver_abs = MINCOST (TTY_CM (d).ver_abs, evalcost);
-
- #undef MINCOST
- #undef COST
- }
-
- /*
- * Calculate the cost to move from (srcy, srcx) to (dsty, dstx) using
- * up and down, and left and right, and motions. If doit is set
- * actually perform the motion.
- */
-
- #ifdef NOT_YET
- static int
- calccost (struct frame *f, int srcy, int srcx, int dsty, int dstx, int doit)
- {
- struct device *d = XDEVICE (FRAME_DEVICE (f));
- int totalcost = 0;
- int deltay, deltax;
- char *motion;
- int motion_cost;
-
- #if 0
- int ntabs, n2tabs, tabx, tab2x, tabcost;
- #endif
-
- cmputc_device = d;
- #if 0
- /* If have just wrapped on a terminal with xn,
- don't believe the cursor position: give up here
- and force use of absolute positioning. */
- if (curX == Wcm.cm_cols)
- goto fail;
- #endif
-
- deltay = dsty - srcy;
- if (!deltay)
- goto calculate_x;
-
- if (deltay < 0)
- {
- motion = TTY_CM (d).up;
- motion_cost = TTY_COST (d).cm_up;
- deltay = -deltay;
- }
- else
- {
- motion = TTY_CM (d).down;
- motion_cost = TTY_COST (d).cm_down;
- }
-
- if (motion_cost == EXPENSIVE)
- {
- /* if (doit) */
- /* #### printing OOF is not acceptable */
- return motion_cost;
- }
-
- totalcost = motion_cost * deltay;
-
- if (doit)
- while (--deltay >= 0)
- tputs (motion, 1, cmputc);
-
- calculate_x:
-
- deltax = dstx - srcx;
- if (!deltax)
- goto done;
-
- if (deltax < 0)
- {
- motion = TTY_CM (d).left;
- motion_cost = TTY_COST (d).cm_left;
- deltax = -deltax;
- }
- else
- {
- motion = TTY_CM (d).right;
- motion_cost = TTY_COST (d).cm_right;
- }
-
- if (motion_cost == EXPENSIVE)
- {
- /* if (doit) */
- /* #### printing OOF is not acceptable */
- return motion_cost;
- }
-
- totalcost += motion_cost * deltax;
-
- if (doit)
- while (--deltax >= 0)
- tputs (motion, 1, cmputc);
-
- done:
- return totalcost;
- }
- #endif /* NOT_YET */
-
- #define USEREL 0
- #define USEHOME 1
- #define USELL 2
- #define USECR 3
-
- #if OLD_CURSOR_MOTION_SHIT
- void
- cmgoto (struct frame *f, int row, int col)
- {
- struct device *d = XDEVICE (FRAME_DEVICE (f));
- char *motion;
- #if 0
- int frame_x = FRAME_CURSOR_X(f);
- int frame_y = FRAME_CURSOR_Y(f);
- int relcost, directcost, llcost;
- int homecost;
- int use;
- char *dcm;
- #endif
-
- cmputc_device = d;
-
- /* First the degenerate case */
- #if 0
- if (row == frame_y && col == frame_x)
- return;
- #endif
-
- /* #### something is fucked with the non-absolute cases */
- motion = tgoto (TTY_CM (d).abs, col, row);
- tputs (motion, 1, cmputc);
- DEVICE_TTY_DATA (d)->cursor_x = col;
- DEVICE_TTY_DATA (d)->cursor_y = row;
- return;
-
- #if 0
- if (frame_y >= 0 && frame_x >= 0)
- {
- /*
- * Pick least-cost motions
- */
-
- relcost = calccost (f, frame_y, frame_x, row, col, 0);
- use = USEREL;
-
- homecost = TTY_COST (d).cm_home;
- if (homecost < EXPENSIVE)
- homecost += calccost (f, 0, 0, row, col, 0);
-
- if (homecost < relcost)
- {
- relcost = homecost;
- use = USEHOME;
- }
-
- llcost = TTY_COST (d).cm_low_left;
- if (llcost < EXPENSIVE)
- llcost += calccost (f, frame_y - 1, 0, row, col, 0);
-
- if (llcost < relcost)
- {
- relcost = llcost;
- use = USELL;
- }
-
- #if 0
- if ((crcost = Wcm.cc_cr) < BIG) {
- if (Wcm.cm_autolf)
- if (curY + 1 >= Wcm.cm_rows)
- crcost = BIG;
- else
- crcost += calccost (curY + 1, 0, row, col, 0);
- else
- crcost += calccost (curY, 0, row, col, 0);
- }
- if (crcost < relcost)
- relcost = crcost, use = USECR;
- #endif
-
- directcost = TTY_COST (d).cm_abs;
- dcm = TTY_CM (d).abs;
-
- if (row == frame_y && TTY_COST (d).cm_hor_abs < EXPENSIVE)
- {
- directcost = TTY_COST (d).cm_hor_abs;
- dcm = TTY_CM (d).hor_abs;
- }
- else if (col == frame_x && TTY_COST (d).cm_ver_abs < EXPENSIVE)
- {
- directcost = TTY_COST (d).cm_ver_abs;
- dcm = TTY_CM (d).ver_abs;
- }
- }
- else
- {
- directcost = 0;
- relcost = 100000;
- dcm = TTY_CM (d).abs;
- }
-
- /*
- * In the following comparison, the = in <= is because when the costs
- * are the same, it looks nicer (I think) to move directly there.
- */
- if (directcost <= relcost)
- {
- /* compute REAL direct cost */
- cm_cost_counter = 0;
- motion = (dcm == TTY_CM (d).hor_abs
- ? tgoto (dcm, row, col)
- : tgoto (dcm, col, row));
- tputs (motion, 1, evalcost);
- if (cm_cost_counter <= relcost)
- { /* really is cheaper */
- tputs (motion, 1, cmputc);
- FRAME_CURSOR_Y (f) = row;
- FRAME_CURSOR_X (f) = col;
- return;
- }
- }
-
- switch (use)
- {
- case USEHOME:
- tputs (TTY_CM (d).home, 1, cmputc);
- FRAME_CURSOR_X (f) = 0;
- FRAME_CURSOR_Y (f) = 0;
- break;
-
- case USELL:
- tputs (TTY_CM (d).low_left, 1, cmputc);
- FRAME_CURSOR_Y (f) = FRAME_HEIGHT (f) - 1;
- FRAME_CURSOR_X (f) = 0;
- break;
-
- #if 0
- case USECR:
- tputs (Wcm.cm_cr, 1, cmputc);
- if (Wcm.cm_autolf)
- curY++;
- curX = 0;
- break;
- #endif
- }
-
- (void) calccost (f, FRAME_CURSOR_Y (f), FRAME_CURSOR_X (f), row, col, 1);
- FRAME_CURSOR_Y (f) = row;
- FRAME_CURSOR_X (f) = col;
- #endif
- }
- #endif /* OLD_CURSOR_MOTION_SHIT */
-
- /*****************************************************************************
- cmgoto
-
- This function is responsible for getting the cursor from its current
- location to the passed location in the most efficient manner
- possible.
- ****************************************************************************/
- void
- cmgoto (struct frame *f, int row, int col)
- {
- struct device *d = XDEVICE (f->device);
- char *motion;
-
- cmputc_device = d;
-
- /* First make sure that we actually have to do any work at all. */
- if (DEVICE_TTY_CURSOR_X (d) == col && DEVICE_TTY_CURSOR_Y (d) == row)
- return;
-
- /* #### Need to reimplement cost analysis and potential relative
- movement. */
-
- /* If all else fails, use absolute movement. */
- motion = tgoto (TTY_CM (d).abs, col, row);
- tputs (motion, 1, cmputc);
- DEVICE_TTY_CURSOR_X (d) = col;
- DEVICE_TTY_CURSOR_Y (d) = row;
- }
-
- #if 0
- /* Clear out all terminal info.
- Used before copying into it the info on the actual terminal.
- */
-
- void
- Wcm_clear (void)
- {
- memset (&Wcm, 0, sizeof Wcm);
- UP = 0;
- BC = 0;
- }
- #endif
-
- #if 0
- /*
- * Initialized stuff
- * Return 0 if can do CM.
- * Return -1 if cannot.
- * Return -2 if size not specified.
- */
-
- int
- Wcm_init (void)
- {
- #if 0
- if (Wcm.cm_abs && !Wcm.cm_ds)
- return 0;
- #endif
- if (Wcm.cm_abs)
- return 0;
- /* Require up and left, and, if no absolute, down and right */
- if (!Wcm.cm_up || !Wcm.cm_left)
- return - 1;
- if (!Wcm.cm_abs && (!Wcm.cm_down || !Wcm.cm_right))
- return - 1;
- /* Check that we know the size of the frame.... */
- if (Wcm.cm_rows <= 0 || Wcm.cm_cols <= 0)
- return - 2;
- return 0;
- }
- #endif
-